/***********************************************************************
    filename:   CEGUIRenderedStringComponent.h
    created:    24/05/2009
    author:     Paul Turner
 *************************************************************************/

#ifndef _HgeGuiRenderedStringComponent_h_
#define _HgeGuiRenderedStringComponent_h_

#include "hgeForwardRef.h"
#include "hgeVector.h"
#include "hgeRect.h"
#include "hgecolor.h"
#include "hgeGuiWindow.h"

/*!
\brief
    Base class representing a part of a rendered string.  The 'part' represented
    may be a text string, an image or some other entity.
*/
class RenderedStringComponent
{
public:
    //! Destructor.
    virtual ~RenderedStringComponent();

    //! Set the VerticalFormatting option for this component.
    void setVerticalFormatting(VerticalFormatting fmt);
    //! return the current VerticalFormatting option.
    VerticalFormatting getVerticalFormatting() const;
    //! set the padding values.
    void setPadding(const hgeRect& padding);
    //! set the left padding value.
    void setLeftPadding(const float padding);
    //! set the right padding value.
    void setRightPadding(const float padding);
    //! set the top padding value.
    void setTopPadding(const float padding);
    //! set the Bottom padding value.
    void setBottomPadding(const float padding);
    //! return the current padding value hgeRect.
    const hgeRect& getPadding() const;
    //! return the left padding value.
    float getLeftPadding() const;
    //! return the right padding value.
    float getRightPadding() const;
    //! return the top padding value.
    float getTopPadding() const;
    //! return the bottom padding value.
    float getBottomPadding() const;
    //! set the aspect-lock state
    void setAspectLock(const bool setting);
    //! return the aspect-lock state
    bool getAspectLock() const;

    //! draw the component.
    virtual void draw(GeometryBuffer& buffer, const Vector2& position,
                      const ColourRect* mod_colours,
                      const hgeRect* clip_rect,
                      const float vertical_space,
                      const float space_extra) const = 0;

    //! return the pixel size of the rendered component.
    virtual Size getPixelSize() const = 0;

    //! return whether the component can be split
    virtual bool canSplit() const = 0;

    /*!
    \brief
        split the component as close to split_point as possible, returning a
        new RenderedStringComponent of the same type as '*this' holding the
        left side of the split, and leaving the right side of the split in
        this object.
    
    \exception InvalidRequestException
        thrown if the RenderedStringComponent does not support being split.
    */
    virtual RenderedStringComponent* split(float split_point,
                                           bool first_component) = 0;

    //! clone this component.
    virtual RenderedStringComponent* clone() const = 0;

    //! return the total number of spacing characters in the string.
    virtual size_t getSpaceCount() const = 0;

protected:
    //! Protected constructor.
    RenderedStringComponent();

    //! Rect object holding the padding values for this component.
    hgeRect d_padding;
    //! Vertical formatting to be used for this component.
    VerticalFormatting d_verticalFormatting;
    //! true if the aspect ratio should be maintained where possible.
    bool d_aspectLock;
};

//! String component that draws an image.
class RenderedStringTextComponent : public RenderedStringComponent
{
public:
	//! Constructor
	RenderedStringTextComponent();
	RenderedStringTextComponent(const String& text);	
	RenderedStringTextComponent(const String& text, hgeFont* font);
	RenderedStringTextComponent(const String& text, const String& font_name);

	//! Set the text to be rendered by this component.
	void setText(const String& text);
	//! return the text that will be rendered by this component
	const String& getText() const;
	//! set the font to use when rendering the text.
	void setFont(hgeFont* font);	
	//! return the font set to be used.  If 0 the default font will be used.
	hgeFont* getFont() const;
	//! Set the colour values used when rendering this component.
	void setColours(const ColourRect& cr);
	//! Set the colour values used when rendering this component.
	void setColours(const colour& c);
	//! return the ColourRect object used when drawing this component.
	const ColourRect& getColours() const;

	// implementation of abstract base interface
	void draw(GeometryBuffer& buffer, const Vector2& position,
		const ColourRect* mod_colours, const hgeRect* clip_rect,
		const float vertical_space, const float space_extra) const;
	Size getPixelSize() const;
	bool canSplit() const;
	RenderedStringTextComponent* split(float split_point, bool first_component);
	RenderedStringTextComponent* clone() const;
	size_t getSpaceCount() const;

protected:
	static size_t getNextTokenLength(const String& text, size_t start_idx);

	//! pointer to the image drawn by the component.
	String d_text;
	//! Font to use for text rendering, 0 for system default.
	hgeFont* d_font;
	//! ColourRect object describing the colours to use when rendering.
	ColourRect d_colours;
};

//! String component that draws an image.
class RenderedStringImageComponent : public RenderedStringComponent
{
public:
	//! Constructor
	RenderedStringImageComponent();
	RenderedStringImageComponent(const String& imageset, const String& image);
	RenderedStringImageComponent(const Image* image);

	//! Set the image to be drawn by this component.
	void setImage(const String& imageset, const String& image);
	//! Set the image to be drawn by this component.
	void setImage(const Image* image);
	//! return the current set image that will be drawn by this component
	const Image* getImage() const;
	//! Set the colour values used when rendering this component.
	void setColours(const ColourRect& cr);
	//! Set the colour values used when rendering this component.
	void setColours(const colour& c);
	//! return the ColourRect object used when drawing this component.
	const ColourRect& getColours() const;
	//! set the size for rendering the image (0s mean 'normal' size)
	void setSize(const Size& sz);
	//! return the size for rendering the image (0s mean 'normal' size)
	const Size& getSize() const;

	// implementation of abstract base interface
	void draw(GeometryBuffer& buffer, const Vector2& position,
		const ColourRect* mod_colours, const hgeRect* clip_rect,
		const float vertical_space, const float space_extra) const;
	Size getPixelSize() const;
	bool canSplit() const;
	RenderedStringImageComponent* split(float split_point, bool first_component);
	RenderedStringImageComponent* clone() const;
	size_t getSpaceCount() const;

protected:
	//! pointer to the image drawn by the component.
	const Image* d_image;
	//! ColourRect object describing the colours to use when rendering.
	ColourRect d_colours;
	//! target size to render the image at (0s mean natural size)
	Size d_size;
};

//! String component that moves a widget to appear as part of the string.
class RenderedStringWidgetComponent : public RenderedStringComponent
{
public:
	//! Constructor
	RenderedStringWidgetComponent();
	RenderedStringWidgetComponent(const String& widget_name);
	RenderedStringWidgetComponent(Window* widget);

	//! Set the window to be controlled by this component.
	void setWindow(const String& widget_name);
	//! Set the window to be controlled by this component.
	void setWindow(Window* widget);
	//! return the window currently controlled by this component
	const Window* getWindow() const;

	// implementation of abstract base interface
	void draw(GeometryBuffer& buffer, const Vector2& position,
		const ColourRect* mod_colours, const hgeRect* clip_rect,
		const float vertical_space, const float space_extra) const;
	Size getPixelSize() const;
	bool canSplit() const;
	RenderedStringWidgetComponent* split(float split_point, bool first_component);
	RenderedStringWidgetComponent* clone() const;
	size_t getSpaceCount() const;

protected:
	//! pointer to the window controlled by this component.
	Window* d_window;
};

#endif // end of guard _HgeGuiRenderedStringComponent_h_
